#ifndef __PTGUI_WIDGET_H__
#define __PTGUI_WIDGET_H__

#include <sys/list.h>
#include <widgets/object.h>

#define PTGUI_WIDGET_FLAG_HIDE			0x01
#define PTGUI_WIDGET_FLAG_DISABLE		0x02
#define PTGUI_WIDGET_FLAG_FOCUS			0x04
#define PTGUI_WIDGET_FLAG_TRANSPARENT	0x08
#define PTGUI_WIDGET_FLAG_FOCUSABLE		0x10
#define PTGUI_WIDGET_FLAG_DEFAULT		0x00

#define PTGUI_WIDGET_UNHIDE(w)			(w)->flag &= ~PTGUI_WIDGET_FLAG_HIDE
#define PTGUI_WIDGET_HIDE(w)			(w)->flag |= PTGUI_WIDGET_FLAG_HIDE
#define PTGUI_WIDGET_IS_HIDE(w)			((w)->flag & PTGUI_WIDGET_FLAG_HIDE)

#define PTGUI_WIDGET_ENABLE(w)			(w)->flag &= ~PTGUI_WIDGET_FLAG_DISABLE
#define PTGUI_WIDGET_DISABLE(w)			(w)->flag |= PTGUI_WIDGET_FLAG_DISABLE
#define PTGUI_WIDGET_IS_ENABLE(w)		!(w->flag & PTGUI_WIDGET_FLAG_DISABLE)

#define PTGUI_WIDGET_UNFOCUS(w)			(w)->flag &= ~PTGUI_WIDGET_FLAG_FOCUS
#define PTGUI_WIDGET_FOCUS(w)			(w)->flag |= PTGUI_WIDGET_FLAG_FOCUS
#define PTGUI_WIDGET_IS_FOCUSED(w)		((w)->flag & PTGUI_WIDGET_FLAG_FOCUS)

#define PTGUI_WIDGET_IS_FOCUSABLE(w) 	((w)->flag & PTGUI_WIDGET_FLAG_FOCUSABLE)

#define PTGUI_WIDGET_FLAG(w)			((w)->flag)

/** Gets the type of a widget */
#define PTGUI_WIDGET_TYPE   	(ptgui_widget_type_get())
/** Casts the object to a ptgui_widget */
#define PTGUI_WIDGET(obj)   	(PTGUI_OBJECT_CAST((obj), PTGUI_WIDGET_TYPE, ptgui_widget_t))
/** Check if the object is a ptgui_widget */
#define PTGUI_IS_WIDGET(obj)	(PTGUI_OBJECT_CHECK_TYPE((obj), PTGUI_WIDGET_TYPE))

struct ptgui_widget
{
	/* inherit from ptgui_object */
	struct ptgui_object	object;

	/* the parent and root widget */
	struct ptgui_widget	*parent;

	/* the widget children and sibling */
	pt_list_t		sibling;

	/* flag */
	pt_int32_t			flag;

	/* the widget extent */
	ptgui_rect_t		extent;

	/* image surface */
	ptgui_surface_t		*surface;
	ptgui_point_t		offset;

	ptgui_render_handler_ptr render_handler;
	ptgui_frame_handler_ptr frame_handler;

	/* the event handler */
	ptgui_event_handler_ptr event_handler;
} ;

#define PTGUI_EVENT_HANDLER(handler) ((ptgui_event_handler_ptr)(handler))
#define PTGUI_RENDER_HANDLER(handler) ((ptgui_render_handler_ptr)(handler))
#define PTGUI_FRAME_HANDLER(handler) ((ptgui_frame_handler_ptr)(handler))

ptgui_type_t *ptgui_widget_type_get(void);
ptgui_widget_t *ptgui_widget_create(ptgui_type_t *widget_type);
void ptgui_widget_destroy(ptgui_widget_t *widget);

/* set the event handler of widget */
void ptgui_widget_set_event_handler(ptgui_widget_t *widget, ptgui_event_handler_ptr handler);
void ptgui_widget_set_render_handler(ptgui_widget_t *widget, ptgui_render_handler_ptr handler);
void ptgui_widget_set_frame_handler(ptgui_widget_t *widget, ptgui_frame_handler_ptr handler);

/* widget default event handler */
ptgui_page_control_t ptgui_widget_event_handler(ptgui_widget_t *widget, pt_event_t *event);

/* focus and unfocused */
void ptgui_widget_focus(ptgui_widget_t *widget);
void ptgui_widget_unfocus(ptgui_widget_t *widget);

/* get and set rect of widget */
void ptgui_widget_get_rect(ptgui_widget_t *widget, ptgui_rect_t *rect);
void ptgui_widget_set_rect(ptgui_widget_t *widget, const ptgui_rect_t *rect);
void ptgui_widget_set_surface(ptgui_widget_t *widget, ptgui_surface_t *surface, pt_int16_t	x, pt_int16_t y);

/* get the physical position of a logic point on widget */
void ptgui_widget_point_to_device(ptgui_widget_t *widget, ptgui_point_t *point);
/* get the physical position of a logic rect on widget */
void ptgui_widget_rect_to_device(ptgui_widget_t *widget, ptgui_rect_t *rect);

/* get the logic position of a physical point on widget */
void ptgui_widget_point_to_logic(ptgui_widget_t *widget, ptgui_point_t *point);
/* get the logic position of a physical rect on widget */
void ptgui_widget_rect_to_logic(ptgui_widget_t *widget, ptgui_rect_t *rect);

/* move widget and its children to a logic point */
void ptgui_widget_move_to_logic(ptgui_widget_t *widget, int dx, int dy);

/* get the toplevel widget of widget */
ptgui_widget_t *ptgui_widget_get_toplevel(ptgui_widget_t *widget);

void ptgui_widget_show(ptgui_widget_t *widget);
void ptgui_widget_hide(ptgui_widget_t *widget);
void ptgui_widget_update(ptgui_widget_t *widget);

/* get the next sibling of widget */
ptgui_widget_t *ptgui_widget_get_next_sibling(ptgui_widget_t *widget);
/* get the prev sibling of widget */
ptgui_widget_t *ptgui_widget_get_prev_sibling(ptgui_widget_t *widget);

#endif	/* __PTGUI_WIDGET_H__ */